using System;
using System.Collections.Generic;
using System.Text;
using Lizk.SimpleHUD;
using Lizk.DShowPlayer;
using System.Threading;
using System.Diagnostics;

namespace SharpMedia.MDX
{
    public class MDXVideoTV : MDXVideo
    {
        private TVPlayer player;
        private TvSettings settings;
        public MDXVideoTV(MDXForm form, HUDVideo2 video)
            : base(form, video)
        {
            this.settings = (TvSettings)video.Tag;
            video.Tag = null;
            player = new TVPlayer(settings);
        }



        public override void Unload()
        {
            lock (videoLoadLock)
            {
                if (player != null && player.State != PlayerState.NotLoaded)
                {
                    if (!video.Closed && player.State == Lizk.DShowPlayer.PlayerState.Paused || player.State == Lizk.DShowPlayer.PlayerState.Playing)
                    {
                        resumeAfterRestart = player.State == Lizk.DShowPlayer.PlayerState.Playing;
                        this.restart = true;
                        restartPosition = player.Position;
                    }
                    player.Dispose();
                    player = null;
                }

                if (allocator != null)
                    allocator.Dispose();
                allocator = null;

                if (video.Closed)
                    Disposed = true;
            }
        }

        public override void HandleVideoCommand(HUDVideo2.VideoCommands command, object[] parameters)
        {
            if (player == null)
                return;


            switch (command)
            {
                case HUDVideo2.VideoCommands.Load:
                    if (player.State == Lizk.DShowPlayer.PlayerState.NotLoaded)
                    {
                        player.StateChanged += new EventHandler<Lizk.DShowPlayer.PlayerEventArgs>(player_StateChanged);
                        player.LanguageChanged += new EventHandler<LanguageEventArgs>(player_LanguageChanged);
                        player.TrackAmountChanged += new EventHandler(player_TrackAmountChanged);
                        ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o) { LoadVideo((MDXVideoTV)o); }), this);
                    } break;
                case HUDVideo2.VideoCommands.Play:
                    if (player.State == Lizk.DShowPlayer.PlayerState.Loaded || player.State == Lizk.DShowPlayer.PlayerState.Paused)
                    {
                        player.Play();
                    }
                    break;
                case HUDVideo2.VideoCommands.Stop:
                    Unload();
                    break;
                case HUDVideo2.VideoCommands.SetChannel:
                    player.SetChannel((int)parameters[0]);
                    video.Updater.SetCurrentChannel((int)parameters[0]); 
                    break;
            }
        }
        private static void LoadVideo(MDXVideoTV cont)
        {

            lock (videoLoadLock)
            {


                if (cont.Player == null || cont.Player.State == PlayerState.Disposed || !cont.form.DeviceAvailable())
                    return;

                cont.allocator = new Allocator2(cont.form, cont);

                cont.Player.Load(cont.form, cont.allocator);


                // Load Channels
                if (cont.player.State == PlayerState.Loaded)
                {
                    cont.player.SetInputType(0, cont.settings.TunerInput);
                    List<Lizk.SimpleHUD.HUDVideo2.TrackIdentifier> channels = new List<HUDVideo2.TrackIdentifier>();
                    foreach (ChannelInfo ci in cont.settings.Channels)
                    {
                        Lizk.SimpleHUD.HUDVideo2.TrackIdentifier ti = new HUDVideo2.TrackIdentifier();
                        ti.id = ci.Channel;
                        ti.name = ci.Name;
                        channels.Add(ti);
                    }
                    cont.video.Updater.SetChannels(channels);
                    cont.player.SetChannel(channels[0].id);
                }

                // If something went wrong, tell the HUDVideo it.
                if (cont.player.State == PlayerState.Disposed)
                {
                    cont.video.Updater.SetState(HUDVideo2.PlayerState.Error);
                }


                // If the video is supposed to restart. We need to seek to where it stopped last time.
                if (cont.restart)
                {
                    cont.player.Play();
                    if (cont.resumeAfterRestart)
                        cont.player.Play();
                    cont.restart = false;
                }
                cont.video.Updater.SetDuration(cont.Player.Duration);
            }
        }

        public override Player Player
        {
            get { return player; }
        }

        public override void Restart()
        {
            if (player == null)
            {
                player = new TVPlayer(settings);
                video.Load();
            }
        }


        void player_TrackAmountChanged(object sender, EventArgs e)
        {

            List<Lizk.SimpleHUD.HUDVideo2.TrackIdentifier> tracks = new List<HUDVideo2.TrackIdentifier>();
            foreach (KeyValuePair<int, string> kvp in player.Subtitles)
            {
                Lizk.SimpleHUD.HUDVideo2.TrackIdentifier ti = new HUDVideo2.TrackIdentifier();
                ti.id = kvp.Key;
                ti.name = kvp.Value;
                tracks.Add(ti);
            }
            video.Updater.SetSubtitles(tracks);
            tracks.Clear();
            video.Updater.SetActiveSubtitle(player.Subtitle);

            foreach (KeyValuePair<int, string> kvp in player.AudioTracks)
            {
                Lizk.SimpleHUD.HUDVideo2.TrackIdentifier ti = new HUDVideo2.TrackIdentifier();
                ti.id = kvp.Key;
                ti.name = kvp.Value;
                tracks.Add(ti);
            }
            video.Updater.SetAudiotracks(tracks);
            
            video.Updater.SetActiveAudiotrack(player.AudioTrack);

        }

        void player_LanguageChanged(object sender, LanguageEventArgs e)
        {

            if(video.Audiotracks.Count > 0 && video.Audiotracks[video.ActiveAudiotrack].id != e.AudioTrack) 
            {
                video.Updater.SetActiveAudiotrack(e.AudioTrack);
            }
            if (video.Subtitles.Count > 0 && video.Subtitles[video.ActiveSubtitle].id != e.Subtitle)
            {
                video.Updater.SetActiveSubtitle(e.Subtitle);
            }

        }

        void player_StateChanged(object sender, PlayerEventArgs e)
        {

            switch (e.NewState)
            {
                case PlayerState.NotLoaded:
                    video.Updater.SetState(HUDVideo2.PlayerState.NotLoaded);
                    break;
                case PlayerState.Loaded:
                    video.Updater.SetState(HUDVideo2.PlayerState.Stopped);
                    break;
                case PlayerState.Playing:
                    video.Updater.SetState(HUDVideo2.PlayerState.Playing);
                    break;
                case PlayerState.Paused:
                    video.Updater.SetState(HUDVideo2.PlayerState.Paused);
                    break;
                case PlayerState.Disposed:
                    video.Updater.SetState(HUDVideo2.PlayerState.NotLoaded);
                    break;
                case PlayerState.Menu:
                    video.Updater.SetState(HUDVideo2.PlayerState.Menu);
                    break;
                default:
                    break;
            }
        }


    }
}
